import pandas as pd
import numpy as np
from interpret.glassbox import ExplainableBoostingClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import StratifiedKFold
from sklearn.metrics import (
    accuracy_score, precision_score, recall_score, f1_score, roc_auc_score
)

# ====== 1. 数据加载 ======
data = pd.read_csv(r"D:\resources\data\jumbo_2020-2021M_0.25deg_ST_SSS_DO_CHL_SSH_MLD_each_year_tertile.csv")

# ====== 2. 特征与标签 ======
target_col = "Label"  # 二分类标签（0=低产，1=高产）
exclude_cols = ["Catch", "Effort", "CPUE", "Label"]
feature_cols = [col for col in data.columns if col not in exclude_cols]

X = data[feature_cols]
y = data[target_col].astype(int)

# ====== 3. 初始化EBM模型（默认参数） ======
ebm = RandomForestClassifier()
# ebm = ExplainableBoostingClassifier()

# ====== 4. 10折交叉验证 ======
cv = StratifiedKFold(n_splits=10, shuffle=True, random_state=42)

# ====== 5. 存储每折结果 ======
results = []

# ====== 6. 逐折训练与评估 ======
for fold, (train_idx, test_idx) in enumerate(cv.split(X, y), start=1):
    # 生成该折的随机种子（可复现）
    fold_random_state = 42 + fold

    # 初始化模型（保证每折独立随机性）
    # ebm = ExplainableBoostingClassifier(random_state=fold_random_state)
    ebm = RandomForestClassifier(random_state=fold_random_state)
    ebm.fit(X.iloc[train_idx], y.iloc[train_idx])

    y_pred = ebm.predict(X.iloc[test_idx])
    y_prob = ebm.predict_proba(X.iloc[test_idx])[:, 1]

    # 计算指标
    acc = accuracy_score(y.iloc[test_idx], y_pred)
    prec = precision_score(y.iloc[test_idx], y_pred)
    rec = recall_score(y.iloc[test_idx], y_pred)
    f1 = f1_score(y.iloc[test_idx], y_pred)
    roc = roc_auc_score(y.iloc[test_idx], y_prob)

    # 保存结果
    results.append({
        "Fold": fold,
        "Random_State": fold_random_state,
        "Accuracy": acc,
        "Precision": prec,
        "Recall": rec,
        "F1-score": f1,
        "ROC-AUC": roc
    })

# ====== 7. 输出结果表格 ======
results_df = pd.DataFrame(results)
print("\n📘 每折验证结果：")
print(results_df)

print("\n📊 10折交叉验证平均指标：")
print(results_df[['Accuracy', 'Precision', 'Recall', 'F1-score', 'ROC-AUC']].mean())
